﻿
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Extend.Framework.Predicate
{
    /// <summary>
    ///     Lamda 表达式扩展类
    /// </summary>
    public static class PredicateExtensionses
    {
        /// <summary>
        ///     返回为真的 lamda 表达式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns>lamda 表达式</returns>
        public static Expression<Func<T, bool>> True<T>()
        {
            return f => true;
        }

        /// <summary>
        ///     返回为假的 lamda 表达式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns>lamda 表达式</returns>
        public static Expression<Func<T, bool>> False<T>()
        {
            return f => false;
        }


        /// <summary>
        ///     追加 lamda 表达式
        /// </summary>
        /// <typeparam name="T">lamda 表达式</typeparam>
        /// <param name="expLeft">原始 lamda 表达式</param>
        /// <param name="expRight">追加 lamda 表达式</param>
        /// <returns>lamda 表达式</returns>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expLeft,Expression<Func<T, bool>> expRight)
        {
            if (expLeft == null) return expRight;

            ParameterExpression candidateExpr = Expression.Parameter(typeof(T), "candidate");
            var parameterReplacer = new ParameterReplacer(candidateExpr);

            Expression left = parameterReplacer.Replace(expLeft.Body);
            Expression right = parameterReplacer.Replace(expRight.Body);
            BinaryExpression body = Expression.And(left, right);

            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }

        /// <summary>
        ///     追加 lamda 表达式
        /// </summary>
        /// <typeparam name="T">lamda 表达式</typeparam>
        /// <param name="expLeft">原始 lamda 表达式</param>
        /// <param name="expRight">追加 lamda 表达式</param>
        /// <returns>lamda 表达式</returns>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expLeft,Expression<Func<T, bool>> expRight)
        {
            if (expLeft == null) return expRight;

            ParameterExpression candidateExpr = Expression.Parameter(typeof(T), "candidate");
            var parameterReplacer = new ParameterReplacer(candidateExpr);

            Expression left = parameterReplacer.Replace(expLeft.Body);
            Expression right = parameterReplacer.Replace(expRight.Body);
            BinaryExpression body = Expression.Or(left, right);

            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }

        /// <summary>
        /// 扩展动态排序
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <param name="source">IQueryable</param>
        /// <param name="orderByProperty">排序字段</param>
        /// <param name="desc">是否降序</param>
        /// <returns>IQueryable</returns>
        public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty,
bool desc) where TEntity : class
        {
            string command = desc ? "OrderByDescending" : "OrderBy";
            var type = typeof(TEntity);
            var property = type.GetProperty(orderByProperty);
            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExpression = Expression.Lambda(propertyAccess, parameter);
            var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression));
            return source.Provider.CreateQuery<TEntity>(resultExpression);
        }

         
    }
}